{"nbformat":4,"nbformat_minor":0,"metadata":{"colab":{"name":"Task_3.ipynb","provenance":[],"collapsed_sections":[],"toc_visible":true,"machine_shape":"hm"},"kernelspec":{"name":"python3","display_name":"Python 3"},"accelerator":"GPU"},"cells":[{"cell_type":"markdown","metadata":{"id":"y6fw7bMFCywt","colab_type":"text"},"source":["# Description of the problem and solution\n","\n","The problem was a classification task. We had ECG measurements of 4 classes that were unbalanced and of not the same length. We used different techinques to extract features that we used for the classification. For each ECG signal we extracted the autocorrelation, the average and the power. We also extracted 15 coefficients of the FFT. For each ECG using biosspy we extracted the heartbeats, averaged them and created a characteristic average of the same length of each patient. For each of these signals (after normalization) we extracted the energy of the wave, the T, S, P, R, Q peaks, the ST QRS PR intervals, QRS/T and QRS/P ratios, the median, mean and interval of the amplitude and the db2 coefficients. Finally, the library biosspy gave us the locations of peaks in the original wave, the timings as well as the heart beats and their timings. For all of them we calculated the mean, median and standard deviation. We also extracted the mean, median and standard deviation of the differences between the peaks' timings( important feature to classify noise, normal heart rate and abnormal heart rhythms). Using all of these features we trained a GradientBoosting model which was fine-tuned using a Cross-validation grid search. The model has 0.817 mean score in the cross-validation and 0.833 in the public scoreboard."]},{"cell_type":"markdown","metadata":{"id":"7T2EjC51C2Gn","colab_type":"text"},"source":["# Include all the necessary packages"]},{"cell_type":"code","metadata":{"id":"FgYMxlCCU0S1","colab_type":"code","colab":{}},"source":["try:\n","  %tensorflow_version 1.x\n","except Exception:\n","  pass\n","import tensorflow as tf\n","\n","import matplotlib.pyplot as plt\n","import numpy as np\n","import pandas as pd\n","\n","from sklearn.model_selection import train_test_split\n","\n","from sklearn.model_selection import KFold\n","from sklearn.metrics import balanced_accuracy_score\n","\n","!pip install biosppy\n","import biosppy as biosppy\n","\n","!pip install PyWavelets\n","import pywt\n","\n","from sklearn.preprocessing import normalize\n","\n","from scipy import stats\n","from statistics import pstdev,variance\n","\n","from sklearn.ensemble import GradientBoostingClassifier\n","from sklearn.metrics import confusion_matrix\n","from sklearn.metrics import f1_score"],"execution_count":0,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"r-4earmkC5yq","colab_type":"text"},"source":["# Load the data from the CSV files"]},{"cell_type":"code","metadata":{"id":"zDu0DZLz-YkX","colab_type":"code","colab":{}},"source":["df = pd.read_csv('/content/X_train.csv', header=0)\n","dataset_x = df.copy()\n","array = np.array(dataset_x)\n","\n","column_names_y = ['id','y']\n","raw_dataset_y = pd.read_csv('/content/y_train.csv', names=column_names_y,\n","                      na_values = \"?\", comment='\\t',\n","                      sep=\",\", skipinitialspace=True, skiprows=True)\n","\n","dataset_y = raw_dataset_y.copy()\n","dataset_y.head()\n","\n","dataset_y.pop(\"id\")\n","dataset_x.pop(\"id\")\n","\n","dataset_x = np.array(dataset_x)\n","dataset_y = np.array(dataset_y)"],"execution_count":0,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"_77Ty8H5C68k","colab_type":"text"},"source":["# Extract features\n","\n","In the cells below we extract features from the ECG diagrams in order to classify the heartbeats. We extracted the autocorrelation of the singal, the average and the power. We also extracted 15 coefficients of the FFT. For each ECG using biosspy we extracted the heartbeats, averaged them and created a characteristic average of each patient. For each of these signals (after normalization) we extracted the energy of the wave, the T, S, P, R, Q peaks, the ST QRS PR intervals, QRS/T and QRS/P ratios, the median, mean and interval of the amplitude and the db2 coefficients. Finally, the library biosspy gave us the location of peaks in the original wave, the timings as well as the heart beats and their timings. For all of them we calculated the mean, median and standard deviation. We also extracted the mean, median and standard deviation of the differences between the peaks' timings important feature to classify noise, normal heart rate and abnormal heart rhythms."]},{"cell_type":"code","metadata":{"id":"ag6WmIqs0lX-","colab_type":"code","colab":{}},"source":["# FFT, power, average and autocorrelation\n","a = dataset_x\n","\n","autocorr = []\n","ptp = []\n","avg = []\n","fft=[]\n","\n","for i in range(len(a)):\n","\n","  h = a[i]\n","  h = h[~np.isnan(h)]\n","\n","  h_series = pd.Series(h)\n","  corr = h_series.autocorr(lag=2)\n","  autocorr.append(corr)\n","\n","  avg.append(np.average(h))\n","  ptp.append(np.ptp(h))\n","\n","  f = np.fft.fft(h)\n","  array = f[0:800]\n","  n = 15\n","  indices = array.argsort()[-n:][::-1]\n","  fft.append(indices)\n","\n","new_autocorr = np.transpose(np.array([autocorr]))\n","ptp = np.transpose(np.array([ptp]))\n","avg = np.transpose(np.array([avg]))\n","fft_np = np.array(fft)"],"execution_count":0,"outputs":[]},{"cell_type":"code","metadata":{"id":"7Ko6NV3EDTpg","colab_type":"code","colab":{}},"source":["#Padding the sequence with the values in last row to max length\n","to_pad = 17814\n","new_seq = []\n","for one_seq in dataset_x:\n","    one_seq = one_seq[~np.isnan(one_seq)]\n","    len_one_seq = len(one_seq)\n","    last_val = one_seq[-1]\n","    n = to_pad - len_one_seq\n","    to_concat = np.repeat(0, n)\n","    new_one_seq = np.concatenate([one_seq, to_concat])\n","    new_seq.append(new_one_seq)\n","final_seq = np.stack(new_seq)\n","\n","dataset_x = np.asarray(final_seq)"],"execution_count":0,"outputs":[]},{"cell_type":"code","metadata":{"id":"8Ss56jfRCe-L","colab_type":"code","colab":{}},"source":["# Extract using biosspy\n","ts_list = []\n","filtered_list=[]\n","rpeaks_list=[]\n","templates_ts_list=[]\n","templates_list=[]\n","heart_rate_ts_list=[]\n","heart_rate_list=[]\n","\n","for i in range(len(dataset_x)):\n","    print (i)\n","    ts, filtered, rpeaks, templates_ts, templates, heart_rate_ts, heart_rate = biosppy.signals.ecg.ecg(signal=dataset_x[i], sampling_rate=300.0, show=False)\n","    filtered_list.append(filtered)\n","    rpeaks_list.append(rpeaks)\n","    templates_ts_list.append(templates_ts)\n","    templates_list.append(templates)\n","    heart_rate_ts_list.append(heart_rate_ts)\n","    heart_rate_list.append(heart_rate)\n","    ts_list.append(ts)"],"execution_count":0,"outputs":[]},{"cell_type":"code","metadata":{"id":"Wet_8Dva-Zn7","colab_type":"code","outputId":"3b946024-0748-490a-98c0-b2427cdf52de","executionInfo":{"status":"ok","timestamp":1575037522237,"user_tz":-60,"elapsed":252698,"user":{"displayName":"Konstantinos Barmpas","photoUrl":"https://lh3.googleusercontent.com/a-/AAuE7mBt2uf-fWQSBS5kgExkK-WbV0w0LBJjXlW2NUFbhA=s64","userId":"01106354619873994193"}},"colab":{"base_uri":"https://localhost:8080/","height":266}},"source":["# Normalize the data and find the average characteristic heartbeat of each patient\n","normalized_templates=[]\n","patients_heartbeats = []\n","for i in range(len(templates_list)):\n","  normalized_templates.append(normalize(templates_list[i]))\n","  patients_heartbeats.append(sum(normalized_templates[i])/len(normalized_templates[i]))\n","\n","plt.plot(patients_heartbeats[0])\n","plt.show()"],"execution_count":0,"outputs":[{"output_type":"display_data","data":{"image/png":"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\nwFdKqQ7i/wPNr43u+DhuLQAAAABJRU5ErkJggg==\n","text/plain":["<Figure size 432x288 with 1 Axes>"]},"metadata":{"tags":[]}}]},{"cell_type":"code","metadata":{"id":"c51Ql0pX-aMh","colab_type":"code","outputId":"8ca15e34-a63b-4c32-a81e-9a999f77b200","executionInfo":{"status":"ok","timestamp":1575037522238,"user_tz":-60,"elapsed":252672,"user":{"displayName":"Konstantinos Barmpas","photoUrl":"https://lh3.googleusercontent.com/a-/AAuE7mBt2uf-fWQSBS5kgExkK-WbV0w0LBJjXlW2NUFbhA=s64","userId":"01106354619873994193"}},"colab":{"base_uri":"https://localhost:8080/","height":265}},"source":["# Extarct all the peaks / Visualization\n","patient_current = patients_heartbeats[347]\n","\n","# Find the peak\n","index = np.where(patient_current==max(patient_current))\n","R = index[0]\n","\n","# First-half\n","first_half = patient_current[0:R[0]]\n","index = np.where(patient_current==min(first_half[R[0]-30:R[0]]))\n","\n","Q = index[0]\n","index = np.where(first_half[0:Q[0]]==max(first_half[0:Q[0]]))\n","P = index[0]\n","\n","#Second half\n","second_half = patient_current[R[0]+1:] \n","index = np.where(patient_current==min(second_half[0:30]))\n","S = index[0]\n","\n","second_half = second_half[S[0]-R[0]+1:]\n","index = np.where(patient_current==max(second_half))\n","T = index[0] \n","\n","plt.plot(patient_current)\n","plt.scatter(R,patient_current[R],label='R')\n","plt.scatter(S,patient_current[S],label='S')\n","plt.scatter(Q,patient_current[Q],label='Q')\n","plt.scatter(P,patient_current[P],label='P')\n","plt.scatter(T,patient_current[T],label='T')\n","plt.plot(np.arange(0, 180),np.zeros(180), 'r--') \n","plt.legend()\n","plt.show()"],"execution_count":0,"outputs":[{"output_type":"display_data","data":{"image/png":"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\nrkJggg==\n","text/plain":["<Figure size 432x288 with 1 Axes>"]},"metadata":{"tags":[]}}]},{"cell_type":"code","metadata":{"id":"kFydCEzm-aaG","colab_type":"code","colab":{}},"source":["# Extarct all the peaks \n","P_list=[]\n","Q_list=[]\n","R_list=[]\n","S_list=[]\n","T_list=[]\n","\n","for i in range(len(patients_heartbeats)):\n","\n","  patient_current = patients_heartbeats[i]\n","\n","  # Find the peak\n","  index = np.where(patient_current==max(patient_current))\n","  R = index[0]\n","\n","  # First-half\n","  first_half = patient_current[0:R[0]]\n","  index = np.where(patient_current==min(first_half[R[0]-30:R[0]]))\n","  Q = index[0]\n","  \n","  index = np.where(first_half[0:Q[0]]==max(first_half[0:Q[0]]))\n","  P = index[0]\n","\n","  #Second half\n","  second_half = patient_current[R[0]+1:] \n","  index = np.where(patient_current==min(second_half[0:30]))\n","  S = index[0]\n","\n","  second_half = second_half[S[0]-R[0]+1:]\n","  index = np.where(patient_current==max(second_half))\n","  T = index[0] \n","\n","  P_list.append(P[0])\n","  Q_list.append(Q[0])\n","  R_list.append(R[0])\n","  S_list.append(S[0])\n","  T_list.append(T[0])"],"execution_count":0,"outputs":[]},{"cell_type":"code","metadata":{"id":"stkGAWfD-anm","colab_type":"code","colab":{}},"source":["# Intervals and Ratios of peaks\n","PR_list = []\n","QRS_list = []\n","ST_list = []\n","\n","for i in range(len(P_list)):\n","  PR_list.append(R_list[i]-P_list[i])\n","  QRS_list.append(S_list[i]-Q_list[i])\n","  ST_list.append(T_list[i]-S_list[i])\n","\n","PR_list = np.array(PR_list).reshape(-1,1)\n","QRS_list = np.array(QRS_list).reshape(-1,1)\n","ST_list = np.array(ST_list).reshape(-1,1)\n","P_list = np.array(P_list).reshape(-1,1)\n","R_list = np.array(R_list).reshape(-1,1)\n","S_list = np.array(S_list).reshape(-1,1)\n","T_list = np.array(T_list).reshape(-1,1)\n","\n","QRS_T_list= np.divide(QRS_list, T_list) \n","QRS_P_list= np.divide(QRS_list, P_list) \n","QRS_T_list=np.nan_to_num(QRS_T_list, nan=0.0,posinf=0.0, neginf=0.0)\n","QRS_P_list=np.nan_to_num(QRS_P_list, nan=0.0,posinf=0.0, neginf=0.0)"],"execution_count":0,"outputs":[]},{"cell_type":"code","metadata":{"id":"4ui9GrLoTSgq","colab_type":"code","colab":{}},"source":["# Range, Mean and Median of amplitudes\n","max_A=[]\n","min_A=[]\n","mean_A=[]\n","median_A=[]\n","\n","for i in range(len(patients_heartbeats)):\n","\n","  patient_current = patients_heartbeats[i]\n","\n","  max_A.append(max(patient_current))\n","  min_A.append(min(patient_current))\n","  mean_A.append(np.mean(patient_current))\n","  median_A.append(np.median(patient_current))"],"execution_count":0,"outputs":[]},{"cell_type":"code","metadata":{"id":"pHP8HdkFUJnt","colab_type":"code","colab":{}},"source":["# Heart rates mean, median, variant and standard deviation\n","hr_mean=[]\n","hr_std=[]\n","hr_median=[]\n","hr_var = []\n","\n","for i in range(len(heart_rate_list)):\n","    d =np.diff(heart_rate_list[i])\n","    hr_mean.append(np.mean(d))\n","    hr_std.append(np.std(d))\n","    hr_median.append(np.median(d))\n","    hr_var.append(np.mean(d)-np.var(d))\n","    \n","hr_mean=np.nan_to_num(hr_mean, nan=0.0)\n","hr_std=np.nan_to_num(hr_std, nan=0.0)\n","hr_median=np.nan_to_num(hr_median, nan=0.0)\n","hr_mode=np.nan_to_num(hr_mode, nan=0.0)\n","hr_var=np.nan_to_num(hr_var, nan=0.0)"],"execution_count":0,"outputs":[]},{"cell_type":"code","metadata":{"id":"N8I_J3qxuKKo","colab_type":"code","colab":{}},"source":["# Timings of peaks mean, median, variant and standard deviation\n","ts_mean=[]\n","ts_std=[]\n","ts_median=[]\n","ts_var = []\n","\n","for i in range(len(ts_list)):\n","    d =np.diff(ts_list[i])\n","    ts_mean.append(np.mean(d))\n","    ts_std.append(np.std(d))\n","    ts_median.append(np.median(d))\n","    ts_var.append(np.mean(d)-np.var(d))\n","    \n","ts_mean=np.nan_to_num(ts_mean, nan=0.0)\n","ts_std=np.nan_to_num(ts_std, nan=0.0)\n","ts_median=np.nan_to_num(ts_median, nan=0.0)\n","ts_var=np.nan_to_num(ts_var, nan=0.0)"],"execution_count":0,"outputs":[]},{"cell_type":"code","metadata":{"id":"-dvgLtiUr42d","colab_type":"code","colab":{}},"source":["# Timings of heart rates mean, median, variant and standard deviation\n","hr_ts_mean=[]\n","hr_ts_std=[]\n","hr_ts_median=[]\n","hr_ts_var = []\n","\n","for i in range(len(heart_rate_ts_list)):\n","    d =np.diff(heart_rate_ts_list[i])\n","    hr_ts_mean.append(np.mean(d))\n","    hr_ts_std.append(np.std(d))\n","    hr_ts_median.append(np.median(d))\n","    hr_ts_var.append(np.mean(d)-np.var(d))\n","    \n","hr_ts_mean=np.nan_to_num(hr_ts_mean, nan=0.0)\n","hr_ts_std=np.nan_to_num(hr_ts_std, nan=0.0)\n","hr_ts_median=np.nan_to_num(hr_ts_median, nan=0.0)\n","hr_ts_var=np.nan_to_num(hr_ts_var, nan=0.0)"],"execution_count":0,"outputs":[]},{"cell_type":"code","metadata":{"id":"sABnt4lKihO7","colab_type":"code","colab":{}},"source":["# Peaks mean, median, variant, mode and standard deviation\n","peaks_mean=[]\n","peaks_std=[]\n","peaks_median=[]\n","peaks_mode=[]\n","peaks_var = []\n","\n","for i in range(len(rpeaks_list)):\n","    peaks_mean.append(np.mean(rpeaks_list[i]))\n","    peaks_std.append(np.std(rpeaks_list[i]))\n","    peaks_median.append(np.median(rpeaks_list[i]))\n","    peaks_mode.append(np.mean(rpeaks_list[i])-stats.mode(rpeaks_list[i])[0])\n","    peaks_var.append(np.var(rpeaks_list[i]))"],"execution_count":0,"outputs":[]},{"cell_type":"code","metadata":{"id":"jzaWcsr_mjvX","colab_type":"code","colab":{}},"source":["# Peaks differences mean, median, variant, mode and standard deviation\n","diff_mean=[]\n","diff_std=[]\n","diff_median=[]\n","diff_mode=[]\n","diff_var = []\n","diff_dev = []\n","\n","for i in range(len(rpeaks_list)):\n","    d = np.diff(rpeaks_list[i])\n","    diff_mean.append(np.mean(d))\n","    diff_std.append(np.std(d))\n","    diff_median.append(np.median(d))\n","    diff_mode.append(np.mean(d)-stats.mode(d)[0])\n","    diff_var.append(np.mean(d)-variance(d))\n","    diff_dev.append(np.mean(d)-pstdev(d))\n","\n","diff_mean=np.nan_to_num(diff_mean, nan=0.0)\n","diff_std=np.nan_to_num(diff_std, nan=0.0)\n","diff_median=np.nan_to_num(diff_median, nan=0.0)\n","diff_mode=np.nan_to_num(diff_mode, nan=0.0)\n","diff_var=np.nan_to_num(diff_var, nan=0.0)\n","diff_dev=np.nan_to_num(diff_dev, nan=0.0)"],"execution_count":0,"outputs":[]},{"cell_type":"code","metadata":{"id":"fMdq5JLrfawO","colab_type":"code","colab":{}},"source":["# db2 coefficients\n","cA_list=[]\n","cD_list=[]\n","\n","for i in range(len(patients_heartbeats)):\n","  cA, cD = pywt.dwt(patients_heartbeats[i], 'db2', mode='periodic')\n","\n","  cA_list.append(cA)\n","  cD_list.append(cD)"],"execution_count":0,"outputs":[]},{"cell_type":"code","metadata":{"id":"ZMtyNz-jgbem","colab_type":"code","colab":{}},"source":["# Energy of the signal\n","energy_list = []\n","\n","for i in range(len(patients_heartbeats)):\n","  energy_list.append(np.sum(patients_heartbeats[i] ** 2))"],"execution_count":0,"outputs":[]},{"cell_type":"code","metadata":{"id":"_z7BbdBhUJ2a","colab_type":"code","colab":{}},"source":["# Prepare data\n","hr_mean = np.array(hr_mean).reshape(-1,1)\n","hr_std = np.array(hr_std).reshape(-1,1)\n","hr_median = np.array(hr_median).reshape(-1,1)\n","hr_var = np.array(hr_var).reshape(-1,1)\n","hr_ts_mean= np.array(hr_ts_mean).reshape(-1,1)\n","hr_ts_std= np.array(hr_ts_std).reshape(-1,1)\n","hr_ts_median= np.array(hr_ts_median).reshape(-1,1)\n","hr_ts_var= np.array(hr_ts_var).reshape(-1,1)\n","ts_mean= np.array(ts_mean).reshape(-1,1)\n","ts_std= np.array(ts_std).reshape(-1,1)\n","ts_median= np.array(ts_median).reshape(-1,1)\n","ts_var = np.array(ts_var).reshape(-1,1)\n","peaks_mean=np.array(peaks_mean).reshape(-1,1)\n","peaks_std=np.array(peaks_std).reshape(-1,1)\n","peaks_median=np.array(peaks_median).reshape(-1,1)\n","peaks_mode=np.array(peaks_mode).reshape(-1,1)\n","diff_mean=np.array(diff_mean).reshape(-1,1)\n","diff_std=np.array(diff_std).reshape(-1,1)\n","diff_median=np.array(diff_median).reshape(-1,1)\n","diff_mode=np.array(diff_mode).reshape(-1,1)\n","diff_var=np.array(diff_var).reshape(-1,1)\n","diff_dev=np.array(diff_dev).reshape(-1,1)\n","max_A=np.array(max_A).reshape(-1,1)\n","min_A=np.array(min_A).reshape(-1,1)\n","mean_A=np.array(mean_A).reshape(-1,1)\n","median_A=np.array(median_A).reshape(-1,1)\n","energy_list =np.array(energy_list).reshape(-1,1)\n","PR_list=np.array(PR_list).reshape(-1,1)\n","ST_list=np.array(ST_list).reshape(-1,1)\n","P_list=np.array(P_list).reshape(-1,1)\n","Q_list=np.array(Q_list).reshape(-1,1)\n","R_list=np.array(R_list).reshape(-1,1)\n","S_list=np.array(S_list).reshape(-1,1)\n","T_list=np.array(T_list).reshape(-1,1)\n","peaks_var=np.array(peaks_var).reshape(-1,1)\n","\n","# Create data array of all the important extracted features\n","data=np.concatenate((fft_np, \n","                     new_autocorr, \n","                     ptp,\n","                     avg,\n","                     energy_list,\n","                     peaks_var,\n","                     peaks_mean, \n","                     peaks_std, \n","                     peaks_median, \n","                     peaks_mode,   \n","                     T_list,\n","                     S_list,\n","                     R_list,\n","                     Q_list,\n","                     P_list,\n","                     ST_list,\n","                     QRS_list,\n","                     PR_list,\n","                     QRS_T_list,\n","                     QRS_P_list,\n","                     max_A-min_A,\n","                     mean_A,\n","                     median_A,\n","                     hr_std,\n","                     hr_mean,\n","                     hr_std,\n","                     hr_var,\n","                     hr_median,\n","                     hr_ts_mean,\n","                     hr_ts_std,\n","                     hr_ts_median,\n","                     hr_ts_var,\n","                     cD_list,\n","                     cA_list,\n","                     diff_dev, \n","                     diff_var, \n","                     diff_std,\n","                     diff_mode, \n","                     diff_mean, \n","                     diff_median,\n","                     ts_mean,\n","                     ts_std,\n","                     ts_median,\n","                     ts_var \n","                     ), axis=1)\n","print (data.shape)"],"execution_count":0,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"ikazS6KJJLvX","colab_type":"text"},"source":["# Train, Test & Confusion in a Random Set "]},{"cell_type":"code","metadata":{"id":"49WhYJaeUJd7","colab_type":"code","colab":{}},"source":["x_train, x_test, y_train, y_test = train_test_split(data, dataset_y, test_size=0.20, random_state=42)\n","\n","clf = GradientBoostingClassifier(learning_rate=0.05, n_estimators=500, max_depth=7, \n","                                 min_samples_split=60, min_samples_leaf=9, subsample=1.0,\n","                                 max_features=50, random_state=0)\n","\n","\n","print ('Training')\n","eval_set = [(x_test, y_test)]\n","clf.fit(x_train, y_train.ravel())\n","    \n","print ('Predicting')\n","predicted_labels = clf.predict(x_test)\n","\n","print ('Scoring')\n","score = f1_score(y_test, predicted_labels, average='micro')\n","\n","print('>%.3f' % score)\n","\n","print ('Scoring')\n","confusion_matrix(y_test, predicted_labels)"],"execution_count":0,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"AwSQuvU1JfEu","colab_type":"text"},"source":["# Cross - Validation of our model"]},{"cell_type":"code","metadata":{"id":"eAhGLWWAkcBa","colab_type":"code","colab":{}},"source":["scores, members = list(), list()\n","\n","repeat = 1 # number of times to do the k-fold cross validation\n","n_folds = 10 # of folds for the cross validation\n","\n","models_list = []\n","\n","for i in range(repeat):\n","\n","  kfold = KFold(n_folds, True, i) # change seed each time\n","  \n","# cross validation\n","  for train_ix, test_ix in kfold.split(data, dataset_y):\n","\n","    print(\"::::::::   # of Training Indices: \", train_ix.size,\n","          \"::::::::::   # of Testing Indices: \", test_ix.size)\n","\n","    # select samples\n","    x_train = []\n","    y_train = []\n","    x_test = []\n","    y_test = []\n","\n","    for i in range(train_ix.size):\n","      x_train.append(data[train_ix[i]])\n","      y_train.append(dataset_y[train_ix[i]])\n","\n","    for i in range(test_ix.size):\n","      x_test.append(data[test_ix[i]])\n","      y_test.append(dataset_y[test_ix[i]])\n","\n","    y_train = np.array(y_train) \n","    x_train = np.array(x_train)\n","    y_test = np.array(y_test) \n","    x_tests= np.array(x_test) \n","\n","    print ('Training')\n","    clf = GradientBoostingClassifier(learning_rate=0.05, n_estimators=500, max_depth=7, \n","                                    min_samples_split=60, min_samples_leaf=9, subsample=1,\n","                                    max_features=50, random_state=0)\n","\n","    clf.fit(x_train, y_train.ravel())\n","    \n","    models_list.append(clf)\n","  \n","    print ('Predicting')\n","    predicted_labels = clf.predict(x_test)\n","\n","    print ('Scoring')     \n","    score = f1_score(y_test, predicted_labels, average='micro')\n","\n","    print('>%.3f' % score)\n","  \n","    scores.append(score)"],"execution_count":0,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"xggF8f0MJjV0","colab_type":"text"},"source":["# Display the Score"]},{"cell_type":"code","metadata":{"id":"Bl8fN_GK2k8D","colab_type":"code","colab":{}},"source":["for i in range(len(scores)): \n","  print(round(scores[i],2))\n","\n","plt.hist(scores);\n","plt.title(\"Score Distribution\")\n","\n","print(\"average score: \", round(np.average(scores),3))\n","print(\"standard dev: \", round(np.std(scores),3))"],"execution_count":0,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"X2gKcv4lJlwR","colab_type":"text"},"source":["# Train in the whole dataset for the final model"]},{"cell_type":"code","metadata":{"id":"QhRd6-yIOzQv","colab_type":"code","colab":{}},"source":["x_train = data\n","y_train = dataset_y\n","\n","y_train = np.array(y_train) \n","x_train= np.array(x_train) \n","\n","print ('Training in the whole dataset')\n","clf = GradientBoostingClassifier(learning_rate=0.05, n_estimators=500, max_depth=7, \n","                                    min_samples_split=60, min_samples_leaf=9, subsample=1,\n","                                    max_features=50, random_state=0)\n","\n","clf.fit(x_train, y_train.ravel())"],"execution_count":0,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"hVZohSjiJn8K","colab_type":"text"},"source":["# Exctract the Data"]},{"cell_type":"code","metadata":{"id":"CPEMAIBbkcR7","colab_type":"code","colab":{}},"source":["df = pd.read_csv('/content/X_test.csv', header=0)\n","dataset_x_test = df.copy()\n","array = np.array(dataset_x_test)\n","\n","dataset_x_test.pop(\"id\")\n","dataset_x_test = np.array(dataset_x_test)\n","\n","a = dataset_x_test\n","autocorr = []\n","ptp = []\n","avg = []\n","fft = []\n","\n","for i in range(len(a)):\n","  h = a[i]\n","  h = h[~np.isnan(h)]\n","  h_series = pd.Series(h)\n","  corr = h_series.autocorr(lag=2)\n","  autocorr.append(corr)\n","  avg.append(np.average(h))\n","  ptp.append(np.ptp(h))\n","  f = np.fft.fft(h)\n","  array = f[0:800]\n","  n = 15\n","  indices = array.argsort()[-n:][::-1]\n","  fft.append(indices)\n","\n","new_autocorr = np.transpose(np.array([autocorr]))\n","ptp = np.transpose(np.array([ptp]))\n","avg = np.transpose(np.array([avg]))\n","fft_np = np.array(fft)\n","\n","to_pad = 17814\n","new_seq = []\n","for one_seq in dataset_x_test:\n","    one_seq = one_seq[~np.isnan(one_seq)]\n","    len_one_seq = len(one_seq)\n","    last_val = one_seq[-1]\n","    n = to_pad - len_one_seq\n","    to_concat = np.repeat(0, n)\n","    new_one_seq = np.concatenate([one_seq, to_concat])\n","    new_seq.append(new_one_seq)\n","final_seq = np.stack(new_seq)\n","dataset_x_test = np.asarray(final_seq)\n","\n","ts_list = []\n","filtered_list=[]\n","rpeaks_list=[]\n","templates_ts_list=[]\n","templates_list=[]\n","heart_rate_ts_list=[]\n","heart_rate_list=[]\n","\n","for i in range(len(dataset_x_test)):\n","  print (i)\n","  ts, filtered, rpeaks, templates_ts, templates, heart_rate_ts, heart_rate = biosppy.signals.ecg.ecg(signal=dataset_x_test[i], sampling_rate=300.0, show=False)\n","  ts_list.append(ts)\n","  filtered_list.append(filtered)\n","  rpeaks_list.append(rpeaks)\n","  templates_ts_list.append(templates_ts)\n","  templates_list.append(templates)\n","  heart_rate_ts_list.append(heart_rate_ts)\n","  heart_rate_list.append(heart_rate)\n","\n","######################################\n","\n","normalized_templates=[]\n","patients_heartbeats = []\n","for i in range(len(templates_list)):\n","  normalized_templates.append(normalize(templates_list[i]))\n","  patients_heartbeats.append(sum(normalized_templates[i])/len(normalized_templates[i]))\n","\n","P_list=[]\n","Q_list=[]\n","R_list=[]\n","S_list=[]\n","T_list=[]\n","\n","for i in range(len(patients_heartbeats)):\n","\n","  patient_current = patients_heartbeats[i]\n","\n","  # Find the peak\n","  index = np.where(patient_current==max(patient_current))\n","  R = index[0]\n","\n","  # First-half\n","  first_half = patient_current[0:R[0]]\n","  index = np.where(patient_current==min(first_half[R[0]-30:R[0]]))\n","  Q = index[0]\n","  \n","  index = np.where(first_half[0:Q[0]]==max(first_half[0:Q[0]]))\n","  P = index[0]\n","\n","  #Second half\n","  second_half = patient_current[R[0]+1:] \n","  index = np.where(patient_current==min(second_half[0:30]))\n","  S = index[0]\n","\n","  second_half = second_half[S[0]-R[0]+1:]\n","  index = np.where(patient_current==max(second_half))\n","  T = index[0] \n","\n","  P_list.append(P[0])\n","  Q_list.append(Q[0])\n","  R_list.append(R[0])\n","  S_list.append(S[0])\n","  T_list.append(T[0])\n","\n","PR_list = []\n","QRS_list = []\n","ST_list = []\n","\n","for i in range(len(P_list)):\n","  PR_list.append(R_list[i]-P_list[i])\n","  QRS_list.append(S_list[i]-Q_list[i])\n","  ST_list.append(T_list[i]-S_list[i])\n","\n","  patient_current = patients_heartbeats[i]\n","\n","PR_list = np.array(PR_list).reshape(-1,1)\n","QRS_list = np.array(QRS_list).reshape(-1,1)\n","ST_list = np.array(ST_list).reshape(-1,1)\n","P_list = np.array(P_list).reshape(-1,1)\n","R_list = np.array(R_list).reshape(-1,1)\n","S_list = np.array(S_list).reshape(-1,1)\n","T_list = np.array(T_list).reshape(-1,1)\n","\n","QRS_T_list= np.divide(QRS_list, T_list) \n","QRS_P_list= np.divide(QRS_list, P_list) \n","QRS_T_list=np.nan_to_num(QRS_T_list, nan=0.0,posinf=0.0, neginf=0.0)\n","QRS_P_list=np.nan_to_num(QRS_P_list, nan=0.0,posinf=0.0, neginf=0.0)\n","\n","max_A=[]\n","min_A=[]\n","mean_A=[]\n","median_A=[]\n","\n","for i in range(len(patients_heartbeats)):\n","  patient_current = patients_heartbeats[i]\n","  max_A.append(max(patient_current))\n","  min_A.append(min(patient_current))\n","  mean_A.append(np.mean(patient_current))\n","  median_A.append(np.median(patient_current))\n","\n","hr_mean=[]\n","hr_std=[]\n","hr_median=[]\n","hr_var = []\n","\n","for i in range(len(heart_rate_list)):\n","    d =np.diff(heart_rate_list[i])\n","    hr_mean.append(np.mean(d))\n","    hr_std.append(np.std(d))\n","    hr_median.append(np.median(d))\n","    hr_var.append(np.mean(d)-np.var(d))\n","\n","hr_mean=np.nan_to_num(hr_mean, nan=0.0)\n","hr_std=np.nan_to_num(hr_std, nan=0.0)\n","hr_median=np.nan_to_num(hr_median, nan=0.0)\n","hr_var=np.nan_to_num(hr_var, nan=0.0)\n","\n","ts_mean=[]\n","ts_std=[]\n","ts_median=[]\n","ts_var = []\n","\n","for i in range(len(ts_list)):\n","    d =np.diff(ts_list[i])\n","    ts_mean.append(np.mean(d))\n","    ts_std.append(np.std(d))\n","    ts_median.append(np.median(d))\n","    ts_var.append(np.mean(d)-np.var(d))\n","    \n","ts_mean=np.nan_to_num(ts_mean, nan=0.0)\n","ts_std=np.nan_to_num(ts_std, nan=0.0)\n","ts_median=np.nan_to_num(ts_median, nan=0.0)\n","ts_var=np.nan_to_num(ts_var, nan=0.0)\n","\n","hr_ts_mean=[]\n","hr_ts_std=[]\n","hr_ts_median=[]\n","hr_ts_var = []\n","\n","for i in range(len(heart_rate_ts_list)):\n","    d =np.diff(heart_rate_ts_list[i])\n","    hr_ts_mean.append(np.mean(d))\n","    hr_ts_std.append(np.std(d))\n","    hr_ts_median.append(np.median(d))\n","    hr_ts_var.append(np.mean(d)-np.var(d))\n","    \n","hr_ts_mean=np.nan_to_num(hr_ts_mean, nan=0.0)\n","hr_ts_std=np.nan_to_num(hr_ts_std, nan=0.0)\n","hr_ts_median=np.nan_to_num(hr_ts_median, nan=0.0)\n","hr_ts_var=np.nan_to_num(hr_ts_var, nan=0.0)\n","\n","peaks_mean=[]\n","peaks_std=[]\n","peaks_median=[]\n","peaks_mode=[]\n","peaks_var = []\n","\n","for i in range(len(rpeaks_list)):\n","    peaks_mean.append(np.mean(rpeaks_list[i]))\n","    peaks_std.append(np.std(rpeaks_list[i]))\n","    peaks_median.append(np.median(rpeaks_list[i]))\n","    peaks_mode.append(np.mean(rpeaks_list[i])-stats.mode(rpeaks_list[i])[0])\n","    peaks_var.append(np.var(rpeaks_list[i]))\n","\n","diff_mean=[]\n","diff_std=[]\n","diff_median=[]\n","diff_mode=[]\n","diff_var = []\n","diff_dev = []\n","\n","for i in range(len(rpeaks_list)):\n","    d = np.diff(rpeaks_list[i])\n","    diff_mean.append(np.mean(d))\n","    diff_std.append(np.std(d))\n","    diff_median.append(np.median(d))\n","    diff_mode.append(np.mean(d)-stats.mode(d)[0])\n","    diff_var.append(np.mean(d)-variance(d))\n","    diff_dev.append(np.mean(d)-pstdev(d))\n","\n","diff_mean=np.nan_to_num(diff_mean, nan=0.0)\n","diff_std=np.nan_to_num(diff_std, nan=0.0)\n","diff_median=np.nan_to_num(diff_median, nan=0.0)\n","diff_mode=np.nan_to_num(diff_mode, nan=0.0)\n","diff_var=np.nan_to_num(diff_var, nan=0.0)\n","diff_dev=np.nan_to_num(diff_dev, nan=0.0)\n","\n","cA_list=[]\n","cD_list=[]\n","\n","for i in range(len(patients_heartbeats)):\n","  cA, cD = pywt.dwt(patients_heartbeats[i], 'db2', mode='periodic')\n","  cA_list.append(cA)\n","  cD_list.append(cD)\n","\n","energy_list = []\n","\n","for i in range(len(patients_heartbeats)):\n","  energy_list.append(np.sum(patients_heartbeats[i] ** 2))\n","\n","hr_mean = np.array(hr_mean).reshape(-1,1)\n","hr_std = np.array(hr_std).reshape(-1,1)\n","hr_median = np.array(hr_median).reshape(-1,1)\n","hr_var = np.array(hr_var).reshape(-1,1)\n","hr_ts_mean= np.array(hr_ts_mean).reshape(-1,1)\n","hr_ts_std= np.array(hr_ts_std).reshape(-1,1)\n","hr_ts_median= np.array(hr_ts_median).reshape(-1,1)\n","hr_ts_var= np.array(hr_ts_var).reshape(-1,1)\n","ts_mean= np.array(ts_mean).reshape(-1,1)\n","ts_std= np.array(ts_std).reshape(-1,1)\n","ts_median= np.array(ts_median).reshape(-1,1)\n","ts_var = np.array(ts_var).reshape(-1,1)\n","peaks_mean=np.array(peaks_mean).reshape(-1,1)\n","peaks_std=np.array(peaks_std).reshape(-1,1)\n","peaks_median=np.array(peaks_median).reshape(-1,1)\n","peaks_mode=np.array(peaks_mode).reshape(-1,1)\n","diff_mean=np.array(diff_mean).reshape(-1,1)\n","diff_std=np.array(diff_std).reshape(-1,1)\n","diff_median=np.array(diff_median).reshape(-1,1)\n","diff_mode=np.array(diff_mode).reshape(-1,1)\n","diff_var=np.array(diff_var).reshape(-1,1)\n","diff_dev=np.array(diff_dev).reshape(-1,1)\n","max_A=np.array(max_A).reshape(-1,1)\n","min_A=np.array(min_A).reshape(-1,1)\n","mean_A=np.array(mean_A).reshape(-1,1)\n","median_A=np.array(median_A).reshape(-1,1)\n","energy_list =np.array(energy_list).reshape(-1,1)\n","PR_list=np.array(PR_list).reshape(-1,1)\n","ST_list=np.array(ST_list).reshape(-1,1)\n","P_list=np.array(P_list).reshape(-1,1)\n","Q_list=np.array(Q_list).reshape(-1,1)\n","R_list=np.array(R_list).reshape(-1,1)\n","S_list=np.array(S_list).reshape(-1,1)\n","T_list=np.array(T_list).reshape(-1,1)\n","peaks_var=np.array(peaks_var).reshape(-1,1)\n","\n","data=np.concatenate((fft_np, \n","                     new_autocorr, \n","                     ptp,\n","                     avg,\n","                     energy_list,\n","                     peaks_var,\n","                     peaks_mean, \n","                     peaks_std, \n","                     peaks_median, \n","                     peaks_mode,   \n","                     T_list,\n","                     S_list,\n","                     R_list,\n","                     Q_list,\n","                     P_list,\n","                     ST_list,\n","                     QRS_list,\n","                     PR_list,\n","                     QRS_T_list,\n","                     QRS_P_list,\n","                     max_A-min_A,\n","                     mean_A,\n","                     median_A,\n","                     hr_std,\n","                     hr_mean,\n","                     hr_std,\n","                     hr_var,\n","                     hr_median,\n","                     hr_ts_mean,\n","                     hr_ts_std,\n","                     hr_ts_median,\n","                     hr_ts_var,\n","                     cD_list,\n","                     cA_list,\n","                     diff_dev, \n","                     diff_var, \n","                     diff_std,\n","                     diff_mode, \n","                     diff_mean, \n","                     diff_median,\n","                     ts_mean,\n","                     ts_std,\n","                     ts_median,\n","                     ts_var, ), axis=1)\n","print (data.shape)\n","#################################\n","\n","predictions = clf.predict(data)\n","\n","index = 0.0\n","with open('final_im2.txt', 'w') as f:\n","    f.write(\"%s\\n\" % \"id,y\")\n","    for predict in predictions:\n","        writing_str = str(index)+','+str(predict.item(0)*1.0)\n","        f.write(\"%s\\n\" % writing_str)\n","        index = index + 1"],"execution_count":0,"outputs":[]}]}